/**
 *
 * Module        : Test Coverages
 * Authors       : Ben Kwint & Arie van der Veek
 * Date          : November 13th 2011
 * Description   : This module calculates the unit size of functions
 *                 again using the methods defined in the Loc metric module
 *
 */
module Metrics::UnitSize

import lang::java::jdt::Java;
import lang::java::jdt::JDT;

import Relation;
import List;
import Set;

import Metrics::Loc;
import Metrics::Regular::StringUtils;
import InOut::Input;

/* 	A unit defined by SIG is for Java a method.
	This module provides methods to calculate different
	measurements for units on java projects.
*/


/* 	countMethods parses a project and then counts methods.
	
	It takes into account the visibility of java described on:
	http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
*/
public tuple[int publicMethods, int privateMethods, int protectedMethods,int noModifierMethods, int totalMethods ] countMethods(AstNodeRel methodBodies){
	
	int publicMethods = 0;
	int privateMethods = 0;
	int protectedMethods = 0;
	int methodDeclarations = 0;
	
	visit(methodBodies) {
		case methodDeclaration(_,_,_,_,_,_,_): methodDeclarations = methodDeclarations + 1;
	    case \public(): publicMethods = publicMethods + 1;
	    case \private(): privateMethods = privateMethods + 1;
	    case \protected(): protectedMethods = protectedMethods + 1;
   	};
   	
   	// Methods without any visibility modifiers is hard to retrieve, so it is calculated.
   	int noModifierMethods = methodDeclarations - (publicMethods + privateMethods + protectedMethods);

   	assert (methodDeclarations)== (publicMethods + privateMethods + protectedMethods+noModifierMethods): "Total amount of methods does not match subs.";
    
    return <publicMethods,privateMethods,protectedMethods,noModifierMethods,methodDeclarations>;
}

/* 	countLOCPerMethod parses a project and then counts the lines of code per method.
	It counts the lines of the annotations before a method declarations, the method 
	declarations and all the follwoing lines excluding emptylines and commments.
	
	Note: It does not take into acount the visibility of the methods,
	so private, protected and public are counted.
*/
public list[tuple[str,int]] countLOCPerMethod(BindingRel methodDecls){
	return
		for( loc fileLocation <- domain(methodDecls ))
		{
	 		int nrOfLines = countLOCForMethod( fileLocation);
			str methodName = getQualifiedMethodsName((head(toList(methodDecls[fileLocation]))));
			append <methodName,nrOfLines>;
		}
}

// Calculates the LOC for a method in a file (location)
public int countLOCForSingleMethod(loc methodLocation){
	list[str] lines =  readCodeBlockFromFile(methodLocation);
	int nrOfLines = countLinesOfCode(lines);
	return nrOfLines;
}